package com.whl.cloud.common.util;

import java.util.Objects;
import java.util.UUID;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.util.WebUtils;

import com.google.gson.Gson;
import com.whl.cloud.constant.SessionConstant;
import com.whl.cloud.model.LoginSession;
import com.whl.cloud.model.SessionResult;
import com.whl.cloud.session.SessionCache;

public class SessionUtil {
	private static Log log = LogFactory.getLog(SessionUtil.class);
	private static ThreadLocal<String> sessionKeyHolder = new ThreadLocal<String>();

	public static void sessionContext(HttpServletRequest request) {
		log.debug("sessionContext is start==============");

		Cookie cookie = WebUtils.getCookie(request, SessionConstant.ACCESS_TOKEN);
		if (cookie == null) {
			sessionKeyHolder.remove();
			log.debug(" the cookie of access_Token is null");
			return;
		}

		String accessToken = cookie.getValue();
		if (StringUtils.isEmpty(accessToken)) {
			return;
		}

		String sessionKey = SessionConstant.AUTH_ACCESS_TOKEN + accessToken;
		SessionResult sessionResult = sessionResult(sessionKey);
		if (sessionResult == null) {
			log.debug(SessionConstant.ACCESS_TOKEN + " sessionResult is null");
			return;
		}

		freshSession(sessionResult);
	}

	public static void destoryLocalSessionHolder() {
		if (log.isDebugEnabled()) {
			log.debug("remove the local sessionKey: " + sessionKeyHolder.get());
		}
		sessionKeyHolder.remove();
	}

	public static SessionResult initSession(LoginSession loginSession, int expire) {
		Objects.requireNonNull(loginSession, "loginSession is null, cannot init");

		// 删除此用户原有的session
		String userKey = SessionConstant.AUTH_USER + loginSession.getId();
		String oldAccessToken = getSessionCache().get(userKey);
		if (StringUtils.isNotEmpty(oldAccessToken)) {
			String sessionKey = SessionConstant.AUTH_ACCESS_TOKEN + oldAccessToken;
			getSessionCache().remove(sessionKey);
			getSessionCache().remove(userKey);
		}

		// 新建session
		String accessToken = DigestUtils.md5Hex(UUID.randomUUID().toString());
		String sessionKey = SessionConstant.AUTH_ACCESS_TOKEN + accessToken;
		SessionResult sessionResult = new SessionResult(loginSession, accessToken, expire);
		String sessionResultJson = new Gson().toJson(sessionResult);
		getSessionCache().put(sessionKey, sessionResultJson, sessionResult.getExpire());
		getSessionCache().put(userKey, sessionResult.getAccessToken(), sessionResult.getExpire());

		return sessionResult;
	}

	public static void freshSession(SessionResult sessionResult) {
		Objects.requireNonNull(sessionResult, "sessionResult is null, cannot fresh");
		LoginSession loginSession = sessionResult.getLoginSession();
		Objects.requireNonNull(loginSession, "loginSession is null, cannot fresh");

		String userKey = SessionConstant.AUTH_USER + loginSession.getId();
		getSessionCache().expire(userKey, sessionResult.getExpire());

		String sessionKey = SessionConstant.AUTH_ACCESS_TOKEN + sessionResult.getAccessToken();
		getSessionCache().expire(sessionKey, sessionResult.getExpire());

		sessionKeyHolder.set(sessionKey);
	}

	public static void createCookie(HttpServletRequest request, HttpServletResponse response, String name,
			String value) {
		Cookie cookie = new Cookie(name, value);
		cookie.setPath("/");
		cookie.setDomain(request.getServerName());
		response.addCookie(cookie);
	}

	public static void destroyCookie(HttpServletRequest request, HttpServletResponse response, String name) {
		Cookie cookie = new Cookie(name, "");
		cookie.setPath("/");
		cookie.setDomain(request.getServerName());
		cookie.setMaxAge(0);
		response.addCookie(cookie);
	}

	public static void removeSession() {
		LoginSession loginSession = getLoginSession();
		if (loginSession != null) {
			String userKey = SessionConstant.AUTH_USER + loginSession.getId();
			String accessToken = getSessionCache().get(userKey);
			getSessionCache().remove(userKey);

			String sessionKey = SessionConstant.AUTH_ACCESS_TOKEN + accessToken;
			getSessionCache().remove(sessionKey);
		}
		sessionKeyHolder.remove();
	}

	public static SessionResult sessionResult(String sessionKey) {

		Objects.requireNonNull(sessionKey, "sessionResult is null");

		String sessionJson = getSessionCache().get(sessionKey);
		if (StringUtils.isEmpty(sessionJson)) {
			return null;
		}

		SessionResult sessionResult = new Gson().fromJson(sessionJson, SessionResult.class);
		return sessionResult;
	}

	public static LoginSession getLoginSession() {

		String sessionKey = sessionKeyHolder.get();
		if (StringUtils.isEmpty(sessionKey)) {
			return null;
		}

		SessionResult sessionResult = sessionResult(sessionKey);
		if (sessionResult == null) {
			return null;
		}

		return sessionResult.getLoginSession();
	}

	public static SessionCache getSessionCache() {
		return SpringUtil.getBean(SessionCache.class);
	}

}
